//---------------------------------INCLUDES-------------------------------------
#include <windows.h>                                                            // Guess...
#include "resources/resources.h"                                                // Resource file ids...
#include <commctrl.h>                                                           // For progress bar...
#include <string.h>                                                             // File I/O...
#include <math.h>                                                               // atof()...
#include <stdlib.h>                                                             // atof()...
#include <stdio.h>                                                              // File I/O...
#include <conio.h>
#include <malloc.h>                                                             // malloc()....
#include <ctype.h>                                                              // toupper() and isalnum()...
#include <time.h>                                                               // Time stamps in install database...
#include <shlobj.h>                                                             // GetLocalAppDataDirectory(void)...
//-------------------------------DEFINITIONS------------------------------------

// DownloadFile() protocol...
#define DOWNLOAD_OK                                     1
#define DOWNLOAD_ERROR_URL                              0
#define DOWNLOAD_ERROR_WINSOCK_DLL                      -1
#define DOWNLOAD_ERROR_WINSOCK_VERSION                  -2
#define DOWNLOAD_ERROR_HOSTNAME                         -3
#define DOWNLOAD_ERROR_CREATE_SOCKET                    -4
#define DOWNLOAD_ERROR_CONNECT                          -5
#define DOWNLOAD_ERROR_SEND                             -6
#define DOWNLOAD_ERROR_FILE_IO                          -7
#define DOWNLOAD_ERROR_SOCKET                           -8
#define DOWNLOAD_ERROR_HTTP_CODE_NOT_200                -9

#define VUPDATE_SCRIPT_URL                              "http://vupdate.servebeer.com/update.ini"
//#define VUPDATE_SCRIPT_URL                              "http://192.168.1.2/update.ini"
#define VUPDATE_SELF_UPDATE_URL                         "http://www.zero47.com/updates/selfupdate.ini"

// Ini parsing engine...
#define INI_ALL_GOOD                                    1
#define INI_ERROR_CANNOT_OPEN                           0
#define INI_ERROR_EMPTY_FILE                            -1
#define INI_ERROR_INVALID_FILE                          -2
#define INI_ERROR_OUT_OF_MEMORY                         -3
#define INI_ERROR_KEY_NOT_FOUND                         -4
#define INI_ERROR_FIELD_NOT_FOUND                       -5
#define INI_ERROR_CANNOT_WRITE                          -6

// GUI stuff for centering window on create...
#define VUPDATE_WIDTH                                   565
#define VUPDATE_HEIGHT                                  241

#define MODE_READY                                      0
#define MODE_DOWNLOAD_SET                               1
#define MODE_DOWNLOADING                                2

// Used in LogInstall() and IsInstalled()...
#define PACKAGE_NOT_INSTALLED                           0
#define PACKAGE_INSTALLED                               1

// Delay between each timer notification...
#define TIMER_DELAY                                     100

// Thread stuff...
#define WM_DOWNLOAD_UPDATES                             WM_USER + 69
#define WM_FINISHED_ONE_DOWNLOAD                        WM_USER + 70
#define WM_FINISHED_ALL_DOWNLOADS                       WM_USER + 71
#define WM_LOAD_OPTIONS                                 WM_USER + 72
#define WM_SAVE_OPTIONS                                 WM_USER + 73
#define WM_IMPLEMENT_OPTIONS                            WM_USER + 74

#ifndef TRUE
    #define TRUE                                        !FALSE
    #define FALSE                                       0
#endif  TRUE

//------------------------------CHOKE-POINT-------------------------------------

#define VUPDATE_VERSION_CHAR                            "1.614"
#define VUPDATE_FILE_VERSION                            1, 6, 1, 4              // For exe image in resource file...
#define VUPDATE_VERSION_FLOAT                           1.614
#define VUPDATE_USER_AGENT                              "vUpdate/1.614 (Dev-C++ WebUpdater)"    // Who we are to server...

//--------------------------------GLOBALS---------------------------------------

//---------------------------------TO-DO----------------------------------------
/*
    * Download preview pic code...
    * List only installed packages... (IsInstalled(char *pszEntryCode))...
    * Checked download list...
    * Description window code...
    * Download / install packages...
    * Fix retarded cfg bug...
    * Fix wrong install bug...
    * Execute...
    * Previews...
    * Self update logic...
    * Test in dev5...
    * Auto center...
    * Break up StartButton()...
    * Versioning support...
    * Grey out download button...
    * Fix dead link execute...
    * Fix scroll bar bug...
    * Fix dead mouse overs...
    * Thread DownloadUpdates()...
    * Random file server selection...
    * Debug log generated from status window...
    * Re-write socket code. Do download manually...
    * Don't remember failed installs...
    * Better debug log / error detect in status window...
    * MessageBox field...
    * Improve devcpp.cfg error control...
    * About button...
    * Options...
    * Implement CloseDev...
    * Implement a remove entry option for installation log...
    * Scroll bar for announcements window...
    * User manual button in about box...
    * Progressive downloads / filesize (in description window)...
    * Implement scroll bar drag logic...
    * Fix annoying glitchy logo box repaint bug...
    * Fix new line char for edit boxes...
    * Tweak scroll bar (mouse wheel / thumb position)...
    * About (license)...
    * Implement "backup file" code...
    * Kill memory leak...
    * Fix list language bug...
    _ Remove 32 package limit. Replace with unlimited...
    * Implement proxy support (ugh)...
    * Show package version in description...
    _ Thread initial connect...
    _ Abort button on initial connect...
    * Reset state on rescan...
    * Show package type in description...
    * Sub language listing in options...
    * Upgrade ini_io lib to 2.3...
    * Replace current self upgrade code with VSU...
    _ Remove stupid devcpp.cfg dependancy and use relative macros...
    _ Implement absolute path to packman.exe and use auto mode...
    _ Replace main window with a resizable dialog box...
*/

//--------------------------------DATA-TYPES------------------------------------

    // This structure holds all the data for our controls...
    typedef struct
    {
        HWND hwnd;
        
        DWORD       dwExStyle;
        LPCTSTR     lpClassName;
        LPCTSTR     lpWindowName;
        DWORD       dwStyle;
        int         x;
        int         y;
        int         nWidth;
        int         nHeight;
        // hwndParent is common data...
        HMENU       hMenu;
        // hInstance is useless too...
        // and so is lpParam....

    }controlData;
    
    // Server settings from script...
    typedef struct
    {
        char    szFileServer[256];
        char    szAnnouncements[1024];

    }ScriptSettings;
    
    // Selfupdate stuff...
    typedef struct
    {
        char    szLatestVersion[256];
        char    szComments[4096];
        char    szURL[4096];

    }SelfUpdateData;
    
    // Package tag. One per package...
    typedef struct
    {
        // Stuff that is in a package tag...
        char    szTitle[32];                                                    // Mandatory...
        char    szEntryCode[64];                                                // Mandatory...
        char    szVersion[64];                                                  // Mandatory...
        char    szType[64];
        char    szFileName[128];                                                // Mandatory...
        char    szFileSize[64];
        char    szDescription[1024];
        char    szDownloadTo[64];                                               // Mandatory...
        char    szMessageBox[1024];
        char    szPreviewPic[128];
        BOOL    bExecute;
        
        // Internal stuff...
        BOOL    bChecked;
        BOOL    bDownloaded;
        BOOL    bDownloadedPreview;

    }Package;
    
    // Internal options. Stores macros and user defined options...
    typedef struct
    {
        // DownloadTo macros...
        char    szRootPath[1024];
        char    szBinPath[1024];
        char    szHelpPath[1024];
        char    szIconsPath[1024];
        char    szIncludePath[1024];
        char    szLibPath[1024];
        char    szLangPath[1024];
        char    szTemplatesPath[1024];
        char    szTempPath[1024];                                                // Not part of NUMBER_OF_MACROS...
        char    szThemesPath[1024];

        // User defined options...
        
            // Interface options...
            BOOL    bInterfaceSmoothProgressBar;
            BOOL    bInterfaceDevTheme;
            BOOL    bInterfacePreviews;
            
            // List settings...
            BOOL    bListPackages;
            BOOL    bListPatches;
            BOOL    bListLanguages;
            char    szListSelectedLanguage[64];
            BOOL    bListHelp;
            BOOL    bListOther;
        
            // Advanced settings...
            BOOL    bAdvancedDebugLog;
            float   fAdvancedBandwidthThrottle;
            BOOL    bAdvancedUseProxy;
            char    szAdvancedProxyServer[1024];
            short   nAdvancedProxyPort;
            
        // Internal stuff...

    }vUpdateOptions;

    // Stuff for DownloadUpdatesThread()...
    typedef struct
    {
        HWND                hwnd;
        controlData         *controls;
        ScriptSettings      *settings;
        Package             *package;
        int                 nNumPackage;
        vUpdateOptions      *options;

    }DownloadUpdatesData;
    
    // Contains data that http server returns in its header...
    typedef struct
    {
        int     nCode;
        char    szDate[64];
        char    szServerType[64];
        char    szLastModified[64];
        char    szETag[64];
        char    szAcceptRanges[32];
        long    nContentLength;
        char    szConnection[32];
        char    szContentType[64];

    }http_header;

//--------------------------------SIGNATURES------------------------------------

    // About box dialog procedure...
    BOOL    CALLBACK AboutDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);

    // Output to debug log...
    void    DebugOut(char *pszString);

    // Display updates...
    void    DisplayUpdates(HWND hwnd, Package *, int nNumPackage, int nTopPackage);

    // Download a file...
    int     DownloadFile(char *pszURL, char *pszFileName, controlData *controls, vUpdateOptions *options);
    
    // Download and install all checked updates...
    DWORD   WINAPI DownloadUpdatesThread(DownloadUpdatesData *);
    
    // Scans string for http header data and dumps it in header structure...
    void    fillHeader(char *pszHeaderBuffer, http_header *header);

    // Scans pszString for '\' + 'n' and replaces with \r\n...
    void    fixNewLine(char *pszString);

    // Fix urls by adding ending '/' if neccessary...
    void    fixURL(char *pszURL);

    // Clear out temporary files / directories...
    void    FlushBuffer(void);

    // Extract host name from a url...
    BOOL    GetHostName(char *pszServerName, char *pszURL);

    // Get user's local app data directory...
    char    *GetLocalAppDataDirectory(void);

    // Get options and macros...
    int     GetOptions(vUpdateOptions *options, controlData *controls);

    // Return formatted time and date...
    char    *getTimeDate();

    // Returns true if pszFile has been deleted or is already gone...
    BOOL    GoodDeleteFile(char *pszFileName);

    // Get a field under pszKey names pszField and store in pszData...
    int     ini_GetField(char *pszFileName, char *pszKey, char *pszField, char *pszData);
    
    // Write a field to pszFileName (an ini file)...
    int     ini_SetField(char *pszFileName, char *pszKey, char *pszField, char *pszData);

    // Implement options that are in the options structure...
    int     ImplementOptions(vUpdateOptions *options, controlData *controls);

    // Check pszBuffer for macro. Insert if need be...
    char    *InsertMacro(char *pszBuffer, vUpdateOptions *options);
    
    // Checks to see if a package is already installed...
    BOOL    IsAlreadyInstalled(Package package, HWND hStatus);

    // Return true if windows NT class OS...
    BOOL    IsNT(void);

    // Logs an installation of pszEntryCode in the database...
    BOOL    LogInstallation(Package package, HWND hStatus);
    
    // Creates a given directory recursively. Will create parent directories as needed...
    BOOL    KickAssCreateDirectory(char *pszPath);

    // Option's box dialog proc...
    BOOL    CALLBACK OptionsDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);

    // Reset vUpdate to blank state...
    void    ResetState(HWND hwnd, controlData *, Package *);

    // Save options and macros into devcpp.cfg...
    int     SaveOptions(vUpdateOptions *options, controlData *controls);
    
    // Selfupdate option's box dialog proc...
    BOOL    CALLBACK SelfUpdateDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);

    // Output text to status window...
    void    StatusOut(char *pszMessage, HWND hwndStatusWindow);

    // Start button code...
    int     StartButton(HWND hwnd, controlData *, ScriptSettings *, Package *, vUpdateOptions *);

    // Count how many times pszKey occured in pszList...
    int     strocc(char *pszList, char *pszKey);

    // If pszString is TRUE, true, or, t, return TRUE...
    BOOL strtobool(char *pszString);

    // Returns an all uppercase copy of pszString...
    char    *strupp(char *pszString);

    // Message proc...
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

//---------------------------------NOTES----------------------------------------
/*
    

*/


